import 'package:im_app/im/util/DbUtil.dart';
import 'package:im_app/im/util/ImConstant.dart';

import '../dao/ImGroupDao.dart';
import '../dao/ImGroupUserDao.dart';
import '../dao/ImSessionDao.dart';
import '../pojo/ImPojo.dart';
import '../socket/dto/business/SendData.dart';
import '../util/UiUtil.dart';
import 'BaseService.dart';

typedef DataChangeHandler = Object Function(String userId, String key, String value);

class GroupChangeDataService {

  // 修改用户名称
  static Object editGroupName(String userId, String groupCode, String groupName) async {
    final groupDao = ImGroupDao();
    final sessionDao = ImSessionDao();
    ImGroup? imGroup = await groupDao.getByCodeAndUserId(groupCode, userId);
    imGroup!.name = groupName;
    imGroup.updateTime = DateTime.now();
    await groupDao.batchUpdates([imGroup]);

    ImSession? session = await sessionDao.getByGroupCodeAndUserId(groupCode, userId);
    session!.name = groupName;
    session.updateTime = DateTime.now();
    await sessionDao.batchUpdates(userId, [session]);

    UiUtil.uiChangeSession(session);
    return 'success';
  }

  // 修改用户名称
  static Object editGroupDescription(String userId, String groupCode, String groupDescription) async {
    final groupDao = ImGroupDao();

    ImGroup? imGroup = await groupDao.getByCodeAndUserId(groupCode, userId);
    imGroup!.description = groupDescription;
    imGroup.updateTime = DateTime.now();
    await groupDao.batchUpdates([imGroup]);

    return 'success';
  }
}

class GroupUserChangeDataService {

  static Object editGroupUserName(String userId, String key, String userName) async {
    final groupDao = ImGroupDao();
    final groupUserDao = ImGroupUserDao();

    int idx = key.lastIndexOf(ImConstant.MESSAGE_SPLIT);
    String groupId = key.substring(0, idx);
    String guUserId = key.substring(idx + ImConstant.MESSAGE_SPLIT.length);
    ImGroup? imGroup = await groupDao.getByCodeAndUserId(groupId, userId);
    ImGroupUser? groupUser = imGroup!.groupUserList?.firstWhere((gu)=>gu.userId == guUserId);

    groupUser!.userName = userName;
    groupUser.updateTime = DateTime.now();
    await groupUserDao.batchUpdates([groupUser].toSet());
    return 'success';
  }

  static Object editGroupShowName(String userId, String key, String isShowNameStr) async {
    final groupDao = ImGroupDao();
    final groupUserDao = ImGroupUserDao();

    int idx = key.lastIndexOf(ImConstant.MESSAGE_SPLIT);
    String groupId = key.substring(0, idx);
    String guUserId = key.substring(idx + ImConstant.MESSAGE_SPLIT.length);
    ImGroup? imGroup = await groupDao.getByCodeAndUserId(groupId, guUserId);
    ImGroupUser? groupUser = imGroup!.groupUserList?.firstWhere((gu)=>gu.userId == guUserId);

    groupUser!.isShowName = bool.parse(isShowNameStr);
    groupUser.updateTime = DateTime.now();
    await groupUserDao.batchUpdates([groupUser].toSet());
    return 'success';
  }
}

class SessionChangeDataService {
  static Object editSessionDisturb(String userId, String userIdOrGroupCode, String isDisturbStr) async {
    final sessionDao = ImSessionDao();
    final groupDao = ImGroupDao();
    final groupUserDao = ImGroupUserDao();
    bool isDisturb = bool.parse(isDisturbStr);
    ImSession? session = await sessionDao.getByUserId(userId, userId, userIdOrGroupCode);
    if (session == null) {
      session = await sessionDao.getByGroupCodeAndUserId(userIdOrGroupCode, userId);
    }

    if (session!.groupCode != null) {
      var imGroup = await groupDao.getByCodeAndUserId(session!.groupCode!, userId);
      var imGroupUser = imGroup!.currentGroupUser!;
      imGroupUser.isDisturb = isDisturb;
      imGroupUser.updateTime = DateTime.now();
      await groupUserDao.batchUpdates([imGroupUser].toSet());
    } else {
      if (session!.fromUserId!.compareTo(session!.toUserId!) >= 0) {
        session.isDisturb = isDisturb;
      } else {
        session.isDisturb2 = isDisturb;
      }
      session.updateTime = DateTime.now();
      await sessionDao.batchUpdates(userId, [session]);
    };

    UiUtil.uiChangeSession(session);

    return 'success';
  }

  static Object editSessionTop(String userId, String userIdOrGroupCode, String isTopStr) async {
    final sessionDao = ImSessionDao();
    final groupDao = ImGroupDao();
    final groupUserDao = ImGroupUserDao();

    bool isTop = bool.parse(isTopStr);
    ImSession? session = await sessionDao.getByUserId(userId, userId, userIdOrGroupCode);
    if (session == null) {
      session = await sessionDao.getByGroupCodeAndUserId(userIdOrGroupCode, userId);
    }

    if (session!.groupCode != null) {
      var imGroup = await groupDao.getByCodeAndUserId(session!.groupCode!, userId);
      var imGroupUser = imGroup!.currentGroupUser!;
      imGroupUser.isTop = isTop;
      imGroupUser.updateTime = DateTime.now();
      await groupUserDao.batchUpdates([imGroupUser].toSet());
    } else {
      if (session!.fromUserId!.compareTo(session!.toUserId!) >= 0) {
        session.isTop = isTop;
      } else {
        session.isTop2 = isTop;
      }

      session.updateTime = DateTime.now();
      await sessionDao.batchUpdates(userId, [session]);
    }

    UiUtil.uiChangeSession(session);
    return 'success';
  }

  static Object editSessionWaking(String userId, String userIdOrGroupCode, String isWakingStr) async {
    final sessionDao = ImSessionDao();
    final groupDao = ImGroupDao();
    final groupUserDao = ImGroupUserDao();

    bool isWaking = bool.parse(isWakingStr);
    ImSession? session = await sessionDao.getByUserId(userId, userId, userIdOrGroupCode);
    if (session == null) {
      session = await sessionDao.getByGroupCodeAndUserId(userIdOrGroupCode, userId);
    }

    if (session!.groupCode != null) {
      var imGroup = await groupDao.getByCodeAndUserId(session!.groupCode!, userId);
      var imGroupUser = imGroup!.currentGroupUser!;
      imGroupUser.isWaking = isWaking;
      imGroupUser.updateTime = DateTime.now();
      await groupUserDao.batchUpdates([imGroupUser].toSet());
    } else {
      if (session!.fromUserId!.compareTo(session!.toUserId!) >= 0) {
        session.isWaking = isWaking;
      } else {
        session.isWaking2 = isWaking;
      }

      session.updateTime = DateTime.now();
      await sessionDao.batchUpdates(userId, [session]);
    }

    UiUtil.uiChangeSession(session);
    return 'success';
  }
}

enum DataTypeEnum {
  group(1, 'group'),
  session(2, "session"),
  groupUser(3, "groupUser"),
  ;

  final int value;
  final String groupName;

  const DataTypeEnum(this.value, this.groupName);

  DataSubTypeEnum getDataSubTypeEnum(DataSubType dataSubType) {
    for (DataSubTypeEnum subTypeEnum in DataSubTypeEnum.values) {
      if (subTypeEnum.group == groupName && subTypeEnum.subType == dataSubType.name) {
        return subTypeEnum;
      }
    }
    throw new Exception("DataSubTypeEnum没有这个枚举值: ${dataSubType.name}");
  }

  static DataTypeEnum getInstance(String name) {
    for(DataTypeEnum changeDataType in DataTypeEnum.values) {
      if (changeDataType.name == name) {
        return changeDataType;
      }
    }
    throw Exception("ChangeDataTypeEnum不包含此处理类型: $name");
  }

  static DataTypeEnum wrap(DataType dataType) {
    DataTypeEnum dataTypeEnum = DataTypeEnum.getInstance(dataType.name);
    return dataTypeEnum;
  }
}

enum DataSubTypeEnum {
  groupName("group", "g_ed_name", GroupChangeDataService.editGroupName),
  groupDesc("group", "g_ed_desc", GroupChangeDataService.editGroupDescription),
  sessionDisturb("session", "s_ed_disturb", SessionChangeDataService.editSessionDisturb),
  sessionTop("session", "s_ed_top", SessionChangeDataService.editSessionTop),
  groupUserName("groupUser", "gu_ed_userName", GroupUserChangeDataService.editGroupUserName),
  groupUserShowName("groupUser", "gu_ed_showName", GroupUserChangeDataService.editGroupShowName),
  ;

  final String group;
  final String subType;
  final DataChangeHandler handler;

  const DataSubTypeEnum(this.group, this.subType, this.handler);

  static List<DataSubTypeEnum> groups(String group) {
    return DataSubTypeEnum.values.where((subType)=>subType.group == group).toList(growable: false);
  }

}